﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

namespace ZCommon.UiExtension;

/// <summary>
/// RichTextBox 扩展方法,用于
/// 追加彩色文本
/// 自动锁定最后一行(除非用户手动滚动)
/// 最大行数限制
/// </summary>
public static class RichTextBoxExtensions
{
    // 是否当前在底部
    private static bool _isAtBottom = true;
    // 最大行数,超过则删除最前面的行,因为每行数据后面都有一个LineBreak,所以乘以2
    private const int _maxLines = 100 * 2;

    public static void AppendTextWithAutoScroll(this RichTextBox richTextBox, string text, Brush color)
    {
        // 初始化检查
        if (richTextBox.Document == null)
        {
            richTextBox.Document = new FlowDocument();
            SetupAutoScrollBehavior(richTextBox);
        }

        // 添加新内容
        var lastParagraph = richTextBox.Document.Blocks.LastBlock as Paragraph;
        if (lastParagraph == null)
        {
            lastParagraph = new Paragraph();
            richTextBox.Document.Blocks.Add(lastParagraph);
        }

        lastParagraph.Inlines.Add(new Run(text) {Foreground = color});
        lastParagraph.Inlines.Add(new LineBreak());

        // 如果行数过多,删除最前面的行,因为每行数据后面都有一个LineBreak,所以乘以2
        while (lastParagraph.Inlines.Count > _maxLines)
        {
            lastParagraph.Inlines.Remove(lastParagraph.Inlines.FirstInline);
        }

        // 如果之前在最底部，自动滚动到新内容
        if (_isAtBottom)
        {
            richTextBox.ScrollToEnd();
        }
    }

    private static void CheckScrollPosition(RichTextBox richTextBox)
    {
        // 获取ScrollViewer
        var scrollViewer = GetScrollViewer(richTextBox);
        if (scrollViewer == null) return;

        // 计算是否在底部
        _isAtBottom =
            scrollViewer.VerticalOffset + scrollViewer.ViewportHeight >= scrollViewer.ExtentHeight - 5; // 5像素的容差
    }

    private static ScrollViewer? GetScrollViewer(DependencyObject depObj)
    {
        if (depObj is ScrollViewer) return depObj as ScrollViewer;

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
        {
            var child = VisualTreeHelper.GetChild(depObj, i);
            var result = GetScrollViewer(child);
            if (result != null) return result;
        }

        return null;
    }

    // 在窗口加载或RichTextBox初始化时调用
    public static void SetupAutoScrollBehavior(this RichTextBox richTextBox)
    {
        var scrollViewer = GetScrollViewer(richTextBox);
        if (scrollViewer == null) return;

        // 监听滚动事件
        scrollViewer.ScrollChanged += (s, e) => { CheckScrollPosition(richTextBox); };
    }
}